package com.sangmo.fts.common;


import com.sangmo.boot.framework.common.session.UserInterface;
import com.sangmo.boot.framework.common.session.UserSession;
import com.sangmo.boot.framework.common.utils.ApplicationUtils;
import com.sangmo.boot.framework.data.json.context.ExtViewContext;
import com.sangmo.boot.framework.event.ByThreadEventDispatcher;
import com.sangmo.fts.common.authority.AuthorityFilterChain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.HashSet;

public class CoreFramework {

	private Logger LOG = LoggerFactory.getLogger(CoreFramework.class);

	private CoreFramework() {
	}
	
	public static CoreFramework getInstance() {
		return new CoreFramework();
	}
	
	public void start() {
		ByThreadEventDispatcher dispatcher = ApplicationUtils.CONTEXT.getBean(ByThreadEventDispatcher.class);
		dispatcher.start();
		ExtViewContext.init();
		TransactionTrace.start();
	}

	public CoreFramework asUser(UserInterface user) {
		UserSession.setAuthorize(new UserSession.Authorize<>(user));
		return this;
	}

	public void run(Executor executor) {
		if (null == ApplicationUtils.CONTEXT) {
			LOG.warn("!!!!!System is still in starting process, it will postpone this execution for 1 sec: " + executor.getClass().getSimpleName());
			try {
				Thread.sleep(1000L);
			} catch (Exception ex) {

			}
			this.run(executor);
			return;
		}
		try {
			this.start();
			executor.run();
			this.stop();
		}
		catch (Exception ex) {
			this.rollback();
			throw ex;
		} finally {

		}
	}
	
	public void stop() {
		this.cleanup();
	}

	public void rollback() {
		this.cleanup();
	}
	
	private void cleanup() {
		AuthorityFilterChain.getInstance().clear();

		ByThreadEventDispatcher dispatcher = ApplicationUtils.CONTEXT.getBean(ByThreadEventDispatcher.class);
		dispatcher.commit();
		ExtViewContext.destroy();
		TransactionTrace.clear();
	}

	public interface Executor {
		void run();
	}

	public CoreFramework asScheduler() {
		return this.asAdmin("SYSTEM.SCHEDULER");
	}

	public CoreFramework asAdmin(String name) {
		UserInterface user = new UserInterface() {
			@Override
			public Serializable getId() {
				return -1L;
			}

			@Override
			public String getName() {
				return name;
			}
		};
		UserSession.setAuthorize(new UserSession.Authorize<>(user));
		UserSession.getAuthorize().setPermissions(new HashSet<String>(){{
			add("*:*");
		}});
		return this;
	}
}
